﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace library
{
    internal partial class p2pFile : IDisposable
    {
        internal byte[] Address;

        internal string Filename;

        internal string SpecifFilename = string.Empty;

        List<Packet> Packets = new List<Packet>();

        List<Packet> PacketsArrived = new List<Packet>();

        internal double ReturnRatio = 1;

        internal ManualResetEvent stoppedEvent = new ManualResetEvent(false);

        int dequeueOffset;

        internal p2pFile(byte[] address, string filename = null, string specifFile = null)
        {
            Address = address;

            Filename = filename;

            if(!string.IsNullOrEmpty(specifFile))
                SpecifFilename = specifFile;

            Thread thread = new Thread(Refresh);

            thread.Start();
        }

        void Refresh()
        {
            while (!Client.Stop)
            {
                Packet packet;

                lock (Packets)
                {
                    if (dequeueOffset == Packets.Count()) //Math.Min(Packets.Count(), 1000))
                    {
                        IEnumerable<Packet> arrived = Packets.Where(x => x.Arrived);

                        Packets.RemoveAll(x => x.Arrived);

                        PacketsArrived.AddRange(arrived);

                        dequeueOffset = 0;

                        if (!Packets.Any())
                            break;
                    }

                    packet = Packets[dequeueOffset++];

                    packet.Get();
                }

                
            }

            lock(Packets)
                if (!Packets.Any())
                    Queue.QueueComplete(this);

            stoppedEvent.Set();
        }

        internal void AddPacket(byte[] address, string filename = null)
        {
            Packet p = new Packet(this, address, filename);

            AddPacket(p);
        }

        void AddPacket(Packet packet)
        {
            lock (Packets)
                Packets.Add(packet);
        }

        bool MayHaveLocalData()
        {
            lock (Packets)
                return Packets.Any(x => x.MayHaveLocalData);
        }

        internal void Stop()
        {
            Peers.idlePeerEvent.Set();
        }

        public void Dispose()
        {
            stoppedEvent.Close();
        }
    }
}
